/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-08 13:56:57
 * @LastEditTime: 2024-12-07 21:02:27
 * @Description: 缓存工具类
 */
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import Redis from 'ioredis';

@Injectable()
export class CacheUtil implements OnModuleInit {
  private static redis: Redis;

  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    const redisInstance = this.moduleRef.get(Redis, { strict: false });
    if (redisInstance) {
      CacheUtil.redis = redisInstance;
    }
  }

  /**
   * 缓存对象
   * @param key 键
   * @param value 值
   * @param timeout 过期时间，单位秒
   */
  static setCacheObject(key: string, value: unknown, timeout: number) {
    if (typeof value === 'string' || value instanceof Buffer) {
      CacheUtil.redis.set(key, value, 'EX', timeout);
    } else {
      CacheUtil.redis.set(key, JSON.stringify(value), 'EX', timeout);
    }
  }

  /**
   * 获取缓存对象
   * @param key 键
   * @returns 泛型 T
   */
  static async getCacheObject<T>(key: string): Promise<T | null> {
    const value = await CacheUtil.redis.get(key);
    if (value === null) {
      return null;
    }
    try {
      return JSON.parse(value) as T;
    } catch (error) {
      throw new Error(`Failed to parse JSON: ${error}`);
    }
  }

  /**
   * 获取字符串缓存对象
   * @param key 键
   * @returns 泛型 T
   */
  static async getCacheString(key: string): Promise<string | null> {
    const value = await CacheUtil.redis.get(key);
    if (value === null) {
      return null;
    }
    return value;
  }

  static async delCache(key: string) {
    await CacheUtil.redis.del(key);
  }

  static async deleteKeysWithPrefix(prefix: string) {
    let cursor = '0';
    let keysToDelete: string[] = [];
    do {
      const result = await CacheUtil.redis.scan(
        cursor,
        'MATCH',
        prefix + '*',
        'COUNT',
        100,
      );
      cursor = result[0];
      keysToDelete = result[1];

      if (keysToDelete.length > 0) {
        await CacheUtil.redis.del(keysToDelete);
      }
    } while (cursor !== '0');
  }

  /**
   * 对指定键进行原子性增加操作
   * @param key 键
   * @param increment 增加的值，默认为1
   * @returns 增加后的值
   */
  static async increment(key: string, increment: number = 1): Promise<number> {
    const newValue = await CacheUtil.redis.incrby(key, increment);
    return newValue;
  }

  /**
   * 对指定键进行原子性减少操作
   * @param key 键
   * @param decrement 减少的值，默认为1
   * @returns 减少后的值
   */
  static async decrement(key: string, decrement: number = 1): Promise<number> {
    const newValue = await CacheUtil.redis.decrby(key, decrement);
    return newValue;
  }
}
